<template>
	<div class="layout-padding">
		<div class="layout-padding-auto layout-padding-view">
			<div class="flex flex-col h-screen md:flex-row bg-slate-50">
				<!-- 左侧面板: 控制区域 -->
				<div class="flex-shrink-0 flex flex-col overflow-y-auto p-5 w-full md:w-1/4 min-w-[280px] bg-white shadow-sm rounded-lg md:mr-4 mb-4 md:mb-0">
					<div class="mb-5">
						<div class="flex justify-between items-center">
							<label class="text-sm font-semibold text-gray-700">模型</label>
							<div class="flex-grow ml-4">
								<ModelList ref="modelListComponent" :model-type="['Image']" />
							</div>
						</div>
					</div>

					<!-- 图片尺寸选择区域 -->
					<div class="mb-6">
						<label class="block mb-3 text-sm font-semibold text-gray-700">图片尺寸</label>
						<div class="grid grid-cols-3 gap-3">
							<div
								v-for="size in imageSizes"
								:key="size.value"
								@click="selectedImageSize = size.value"
								:class="[
									'flex relative justify-center items-center p-2 border rounded-lg cursor-pointer transition-all duration-200',
									selectedImageSize === size.value
										? 'bg-blue-50 border-blue-500 text-blue-600 ring-2 ring-blue-200'
										: 'bg-white border-gray-200 hover:bg-gray-50',
								]"
							>
								<div class="flex flex-col justify-center items-center py-1 w-full">
									<div class="overflow-hidden relative mb-2 w-12 h-8 rounded border border-gray-300 border-dashed">
										<img v-if="size.iconName" :src="getIconUrl(size.iconName)" :alt="size.label" class="object-contain w-full h-full" />
									</div>
									<span class="text-xs font-medium">{{ size.label }}</span>
								</div>
							</div>
						</div>
					</div>

					<div class="space-y-5">
						<!-- 图片数量滑块 -->
						<div>
							<div class="flex justify-between mb-2">
								<label class="text-sm font-semibold text-gray-700">图片数量</label>
								<span class="text-sm font-medium text-gray-600">{{ numberOfImages }}</span>
							</div>
							<el-slider v-model="numberOfImages" :min="1" :max="4" class="mx-1"></el-slider>
						</div>

						<!-- 随机种子输入框 -->
						<div>
							<label class="block mb-2 text-sm font-semibold text-gray-700">种子</label>
							<div class="flex items-center">
								<el-input v-model="seed" placeholder="随机种子" class="flex-grow mr-2"></el-input>
								<el-button
									:icon="RefreshRight"
									@click="randomizeSeed"
									class="flex-shrink-0 transition-transform duration-300 hover:rotate-180"
								></el-button>
							</div>
						</div>

						<!-- 推理步数滑块 -->
						<div>
							<div class="flex justify-between mb-2">
								<label class="text-sm font-semibold text-gray-700">推理步数</label>
								<span class="text-sm font-medium text-gray-600">{{ inferenceSteps }}</span>
							</div>
							<el-slider v-model="inferenceSteps" :min="1" :max="100" :step="1" class="mx-1"></el-slider>
						</div>

						<!-- 引导强度滑块 -->
						<div>
							<div class="flex justify-between mb-2">
								<label class="text-sm font-semibold text-gray-700">引导强度</label>
								<span class="text-sm font-medium text-gray-600">{{ guidanceScale }}</span>
							</div>
							<el-slider v-model="guidanceScale" :min="1" :max="20" :step="0.1" class="mx-1"></el-slider>
						</div>

						<!-- 反向提示词输入框 -->
						<div>
							<label class="block mb-2 text-sm font-semibold text-gray-700">反向提示词</label>
							<el-input type="textarea" :rows="3" v-model="negativePrompt" placeholder="不想在图片中看到的内容" class="w-full rounded-lg"></el-input>
						</div>

						<!-- 上传参考图片 -->
						<div>
							<div class="flex justify-between items-center mb-2">
								<label class="text-sm font-semibold text-gray-700">参考图片 (可选)</label>
								<el-upload
									class="flex justify-start"
									:auto-upload="false"
									:limit="1"
									:on-change="handleImageUpload"
									:on-remove="handleImageRemove"
									accept="image/*"
								>
									<template #trigger>
										<div class="flex">
											<el-button type="primary" size="small" class="rounded-md">选择图片</el-button>
										</div>
									</template>
								</el-upload>
							</div>
						</div>
					</div>
				</div>

				<!-- 中间面板: 图片显示和提示词输入区域 -->
				<div class="flex flex-col flex-grow p-5 mb-4 bg-white rounded-lg shadow-sm md:mr-4 md:mb-0">
					<!-- 图片显示区域 -->
					<div class="flex overflow-hidden relative flex-col flex-grow mb-6 bg-gray-50 rounded-xl border border-gray-200">
						<div v-if="selectedHistoryImage" class="flex justify-center items-center p-2 w-full h-full">
							<img
								:src="baseURL + selectedHistoryImage"
								alt="History Image"
								class="object-contain max-w-full max-h-full rounded-lg shadow-md h-[600px]"
							/>
							<el-button
								class="absolute top-3 right-3 backdrop-blur-sm bg-white/80 hover:bg-white"
								size="small"
								type="default"
								circle
								@click="selectedHistoryImage = null"
								icon="Close"
							></el-button>
						</div>
						<div v-else-if="generatedImageUrls.length > 0" class="w-full h-full">
							<el-carousel
								:initial-index="currentImageIndex"
								height="100%"
								arrow="always"
								indicator-position="outside"
								@change="handleCarouselChange"
								class="h-full image-carousel"
							>
								<el-carousel-item v-for="(url, index) in generatedImageUrls" :key="index" class="flex justify-center items-center h-full">
									<div class="flex justify-center items-center p-4 w-full h-full image-container">
										<img :src="baseURL + url" alt="Generated Image" class="object-contain max-w-full max-h-full rounded-lg shadow-md h-[600px]" />
									</div>
								</el-carousel-item>
							</el-carousel>
						</div>
						<div v-else-if="isGenerating" class="flex flex-col justify-center items-center h-full">
							<el-icon class="text-blue-500 animate-spin" size="48"><Loading /></el-icon>
							<span class="mt-4 font-medium text-gray-600">正在生成图片...</span>
						</div>
						<div v-else class="flex justify-center items-center h-full">
							<div class="p-8 text-center">
								<span class="block mb-2 text-gray-400">图片将在这里显示</span>
								<span class="text-xs text-gray-400">输入提示词并点击生成按钮</span>
							</div>
						</div>
					</div>

					<!-- 示例提示词区域 -->
					<div v-if="!selectedHistoryImage" class="mb-5">
						<div class="flex justify-between items-center mb-3">
							<h3 class="text-sm font-semibold text-gray-700">示例提示词</h3>
							<el-tooltip content="点击使用示例提示词" placement="top">
								<el-icon class="text-gray-400 cursor-help hover:text-gray-600"><InfoFilled /></el-icon>
							</el-tooltip>
						</div>
						<div class="grid grid-cols-1 gap-2 pb-1 max-h-[200px] overflow-y-auto">
							<div
								v-for="example in examplePrompts"
								:key="example"
								@click="prompt = example"
								class="flex items-center p-3 bg-white rounded-lg border border-gray-200 transition-all duration-200 cursor-pointer hover:bg-blue-50 hover:border-blue-300"
							>
								<el-icon class="mr-3 text-blue-500"><ChatLineRound /></el-icon>
								<div class="overflow-hidden">
									<p class="text-sm truncate">{{ truncateText(example, 60) }}</p>
								</div>
							</div>
						</div>
					</div>

					<!-- 提示词输入区域 -->
					<div class="flex flex-col items-center p-4 mt-auto bg-white rounded-lg border border-gray-200 shadow-sm">
						<div v-if="selectedHistoryImage" class="mb-3 w-full text-center">
							<el-tag type="info" effect="light" size="small" class="px-3 py-1 mb-1">
								<el-icon class="mr-1"><InfoFilled /></el-icon>您正在查看历史图片，可以编辑提示词重新生成
							</el-tag>
						</div>
						<div class="flex items-center w-full">
							<el-input
								v-model="prompt"
								placeholder="请输入你的创意指令... "
								class="flex-grow mr-4 prompt-input"
								@keyup.enter.prevent="handlePromptEnter"
								autosize
								type="textarea"
								:maxlength="500"
								:input-style="{
									border: 'none',
									boxShadow: 'none',
									padding: '12px 0px',
									lineHeight: '1.5',
									resize: 'none',
									backgroundColor: selectedHistoryImage ? '#f9f9f9' : 'transparent',
								}"
								resize="none"
							>
							</el-input>
							<el-button
								circle
								type="primary"
								@click="generateImage"
								:loading="isGenerating"
								class="flex justify-center items-center w-14 h-14 min-w-[3.5rem] min-h-[3.5rem] rounded-full shadow-md transition-all duration-300 hover:shadow-lg transform hover:scale-105"
								:disabled="!prompt.trim() && !uploadedImageBase64"
							>
								<el-icon size="26"><Promotion /></el-icon>
							</el-button>
						</div>
					</div>
				</div>

				<!-- 右侧面板: 历史记录 -->
				<div class="flex-shrink-0 w-full md:w-1/4">
					<HistoryPanel
						ref="historyPanelRef"
						title="生成历史"
						material-type="Image"
						thumbnailAlt="Generated Image"
						@item-click="handleHistoryItemClick"
						:default-page-size="pageSize"
						:show-time-column="true"
						class="h-full"
					/>
				</div>
			</div>
		</div>
	</div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { RefreshRight, Promotion, Loading, InfoFilled, ChatLineRound } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import ModelList from './components/widgets/modelList.vue';
import HistoryPanel, { type HistoryItem } from './components/widgets/historyPanel.vue';
import { genImage } from '/@/api/knowledge/aiGen';
import { Local } from '/@/utils/storage';

// Import SVG icons
import imageSize11 from '/@/assets/ai/images/image-size-1-1.svg';
import imageSize12 from '/@/assets/ai/images/image-size-1-2.svg';
import imageSize32 from '/@/assets/ai/images/image-size-3-2.svg';
import imageSize34 from '/@/assets/ai/images/image-size-3-4.svg';
import imageSize169 from '/@/assets/ai/images/image-size-16-9.svg';
import imageSize916 from '/@/assets/ai/images/image-size-9-16.svg';

// SVG icon mapping
const iconMap: Record<string, string> = {
	'image-size-1-1': imageSize11,
	'image-size-1-2': imageSize12,
	'image-size-3-2': imageSize32,
	'image-size-3-4': imageSize34,
	'image-size-16-9': imageSize169,
	'image-size-9-16': imageSize916,
};

// Get the baseURL from environment variables
const baseURL = import.meta.env.VITE_API_URL || '';

// 获取图标URL的辅助函数
const getIconUrl = (iconName: string) => {
	return iconMap[iconName] || '';
};

// 文本截断的辅助函数
const truncateText = (text: string, maxLength: number) => {
	return text?.length > maxLength ? text.substring(0, maxLength) + '...' : text || '';
};

// 左侧面板: 控制数据
const modelListComponent = ref<any>(null); // 模型选择组件引用
const imageSizes = ref([
	{ label: '1:1', value: '1024x1024', iconName: 'image-size-1-1' }, // 方形图片
	{ label: '1:2', value: '720x1440', iconName: 'image-size-1-2' }, // 长形竖图
	{ label: '3:2', value: '960x1280', iconName: 'image-size-3-2' }, // 电影海报比例
	{ label: '3:4', value: '768x1024', iconName: 'image-size-3-4' }, // 肖像/人像比例
	{ label: '16:9', value: '1024x576', iconName: 'image-size-16-9' }, // 宽屏比例
	{ label: '9:16', value: '720x1280', iconName: 'image-size-9-16' }, // 手机屏幕比例
]);

const selectedImageSize = ref('1024x1024'); // 默认图片尺寸为1:1
const numberOfImages = ref(1); // 默认生成图片数量
const seed = ref(''); // 随机种子值
const inferenceSteps = ref(25); // 推理步数，步数越大，生成质量越高但耗时更长
const guidanceScale = ref(7.5); // 引导强度，值越高越忠于提示词
const negativePrompt = ref<string | null>(null); // 反向提示词，指定不希望在图像中出现的内容
const uploadedImageBase64 = ref<string | null>(null); // 上传图片的Base64编码
const uploadedImageFile = ref<File | null>(null); // 上传的图片文件对象

// 右侧面板: 数据
const generatedImageUrl = ref<string>(''); // 当前显示的生成图片URL
const generatedImageUrls = ref<string[]>([]); // 所有生成的图片URL数组
const currentImageIndex = ref(0); // 当前查看的图片索引
const prompt = ref(''); // 提示词输入
const isGenerating = ref(false); // 是否正在生成图片
const selectedHistoryImage = ref<string | null>(null); // 选中的历史图片URL
const examplePrompts = ref([
	// 示例提示词列表
	'埃菲尔铁塔被包裹在彩色丝绸中，日落时分，高清摄影，逼真细节，金色光芒',
	'场景由三个物体组成：一本古老的书籍，一盏复古油灯和一只沉睡的猫，柔和的光线，写实风格',
	'古老的战场，虽然战争已经结束，但残留的盔甲和武器依然散落，薄雾笼罩，史诗般的氛围，8K渲染',
	'纽约城市风光，摩天大楼在雨后闪烁着灯光，湿润的街道反射着霓虹灯，电影质感，广角镜头',
	'梦幻森林场景，巨大的蘑菇和发光植物，小精灵在空中飞舞，魔幻色彩，细腻质感，幻想艺术风格',
]);

// 历史记录和分页相关数据
const pageSize = ref(10);

// 左侧面板: 方法
// 生成随机种子
const randomizeSeed = () => {
	seed.value = String(Math.floor(Math.random() * 1000000000));
};

// 处理图片上传
const handleImageUpload = (file: any) => {
	if (file.raw && file.raw.type && file.raw.type.startsWith('image/')) {
		uploadedImageFile.value = file.raw;
		const reader = new FileReader();
		reader.onload = (e) => {
			if (e.target && e.target.result) {
				uploadedImageBase64.value = e.target.result.toString(); // 转换为Base64
			}
		};
		reader.readAsDataURL(file.raw);
		return false; // 阻止自动上传
	}

	ElMessage.error('请上传有效的图片文件');
	return false;
};

// 处理图片移除
const handleImageRemove = () => {
	uploadedImageFile.value = null;
	uploadedImageBase64.value = null;
};

// 右侧面板: 方法
// 处理回车键按下事件
const handlePromptEnter = (event: KeyboardEvent) => {
	if (event.shiftKey) {
		// 允许Shift+Enter换行
		return;
	}
	generateImage(); // 直接回车则生成图片
};

// 历史面板引用
const historyPanelRef = ref<InstanceType<typeof HistoryPanel> | null>(null);

// 处理历史项目点击 - 新方法，适配historyPanel组件
const handleHistoryItemClick = (item: HistoryItem) => {
	if (item.localUrl) {
		// 显示历史图片
		selectedHistoryImage.value = item.localUrl;
		// 应用提示词
		prompt.value = item.prompt || '';
	} else {
		ElMessage.info('该记录没有图片');
	}
};

// 生成图片的核心方法
const generateImage = async () => {
	if (!prompt.value.trim() && !uploadedImageBase64.value) {
		ElMessage.warning('请输入提示词或上传图片!');
		return;
	}

	isGenerating.value = true;
	generatedImageUrl.value = ''; // 清除之前的图片
	generatedImageUrls.value = []; // 清除之前的图片数组
	selectedHistoryImage.value = null; // 清除选中的历史图片
	currentImageIndex.value = 0; // 重置索引

	try {
		// 获取本地存储的选中模型
		const selectedModel = Local.get(`selectedAiModel:Image`);

		// 准备API调用参数
		const params = {
			model: selectedModel.name, // 选中的AI模型名称
			imageSize: selectedImageSize.value, // 图片尺寸
			batchSize: numberOfImages.value, // 生成图片数量
			seed: seed.value ? Number(seed.value) : undefined, // 随机种子
			numInferenceSteps: inferenceSteps.value, // 推理步数
			guidanceScale: guidanceScale.value, // 引导强度
			negativePrompt: negativePrompt.value || undefined, // 反向提示词
			prompt: prompt.value, // 正向提示词
			image: uploadedImageBase64.value || undefined, // 参考图片（用于图像到图像生成）
		};

		// 调用API生成图片
		const { data: imageUrls } = await genImage(params);
		if (imageUrls && imageUrls.length) {
			generatedImageUrls.value = imageUrls;
			generatedImageUrl.value = imageUrls[0]; // 设置第一张图片为当前显示
			currentImageIndex.value = 0; // 设置为第一张图片
			ElMessage.success('图片生成成功!');

			// 生成成功后刷新历史记录
			historyPanelRef.value?.refreshHistory();
		} else {
			ElMessage.error('图片生成失败, 请稍后重试');
		}
	} catch (error) {
		const errorMessage = error instanceof Error ? error.message : 'Unknown error';
		ElMessage.error(`生成图片时发生错误，请稍后重试: ${errorMessage}`);
	} finally {
		isGenerating.value = false; // 无论成功或失败，都重置生成状态
	}
};

// 处理轮播图当前图片
const handleCarouselChange = (index: number) => {
	currentImageIndex.value = index;
	generatedImageUrl.value = generatedImageUrls.value[index];
};

// 组件初始化
onMounted(() => {
	// 生成随机种子
	randomizeSeed();
});
</script>

<style scoped>
.image-carousel :deep(.el-carousel__arrow) {
	background-color: rgba(30, 58, 138, 0.7);
	border-radius: 9999px;
	transition: all 0.2s;
}

.image-carousel :deep(.el-carousel__arrow:hover) {
	background-color: rgba(30, 58, 138, 0.9);
	transform: scale(1.1);
}

.image-carousel :deep(.el-carousel__indicators) {
	bottom: 10px;
}

.image-carousel :deep(.el-carousel__indicator) {
	padding: 0 4px;
}

.image-carousel :deep(.el-carousel__button) {
	background-color: rgba(30, 58, 138, 0.5);
	border-radius: 4px;
	width: 24px;
	height: 4px;
	transition: all 0.2s;
}

.image-carousel :deep(.el-carousel__indicator.is-active .el-carousel__button) {
	background-color: rgba(30, 58, 138, 0.9);
}

/* 滚动条样式 */
.history-container::-webkit-scrollbar,
.max-h-\[200px\]::-webkit-scrollbar {
	width: 6px;
	height: 6px;
}

.history-container::-webkit-scrollbar-thumb,
.max-h-\[200px\]::-webkit-scrollbar-thumb {
	background: #cbd5e1;
	border-radius: 6px;
}

.history-container::-webkit-scrollbar-track,
.max-h-\[200px\]::-webkit-scrollbar-track {
	background: #f1f5f9;
	border-radius: 6px;
}

@media (max-width: 768px) {
	.flex-col-reverse {
		flex-direction: column-reverse;
	}
}
</style>
